/*
 * combat.h
 *
 *  Created on: Aug 15, 2013
 *      Author: killerg
 */

#ifndef COMBAT_H_
#define COMBAT_H_

#include "share/util.h"


#include "attribute.h"

// ----------------------------------------------------------------------------
// 技能触发点
// ----------------------------------------------------------------------------
enum ESpellPoint {
    ESP_Begin = 0,
    ESP_Combat = 0,        // 进场
    ESP_Attack1 = 1,    // 攻击
    ESP_BeAttack1 = 2,    // 被击
    ESP_Attack2 = 3,    // 反击
    ESP_End = ESP_Attack2+1,
};

// ----------------------------------------------------------------------------
// 技能触发点
// ----------------------------------------------------------------------------
enum ESpriteSkillPoint {
    ESSP_Begin = 0,        // 进场
    ESSP_Attack = 1,    // 攻击时
    ESSP_End = 2,        // 出场
};

// ----------------------------------------------------------------------------
// 技能触发点
// ----------------------------------------------------------------------------
enum EBPoint {
    EBP_Remove = 1,        // 移除时触发
    EBP_Round = 2,        // 每回合触发
};

struct unit_t;
struct player_t;
struct pet_t;
struct sprite_t;

struct combat_unit_t;
struct combat_sprite_t;
struct combat_pet_t;

class OCombat;

// ----------------------------------------------------------------------------
// 精灵
// ----------------------------------------------------------------------------
struct combat_sprite_t {
    combat_unit_t* unit;                        // 阵营
    const tagProtoSprite* proto;                // 精灵原型
    int32_t skill_level[SpriteSkillNum];                        // 精灵技能等级
    int32_t form_level;
    int32_t form_seed;

    combat_sprite_t() {
        unit = NULL;
        proto = NULL;
        form_level = 0;
        form_seed = -1;
        skill_level[0] = skill_level[1] = 0;
    }
    ~combat_sprite_t() {
        unit = NULL;
        proto = NULL;
        skill_level[0] = skill_level[1] = 0;
    }

    bool init(sprite_t* sprite);
    void destroy();

    bool check_skill(int essp, combat_unit_t*const* units);
};

// ----------------------------------------------------------------------------
// 技能
// ----------------------------------------------------------------------------
struct combat_skill_t {
    const tagProtoSkill* proto;                    // 技能原型
    bool active;                                // 是否正在释放
    int32_t cast_num;                            // 释放次数

    combat_skill_t() {
        proto = NULL;
        active = false;
        cast_num = 0;
    }
    ~combat_skill_t() {
        proto = NULL;
        active = false;
        cast_num = 0;
    }

    void begin_cast(int round, int esp, combat_pet_t* caster, combat_pet_t* target);
    void end_cast(int esp, combat_pet_t* caster, combat_pet_t* target);
    void do_cast(int esp, combat_pet_t* caster, combat_pet_t* target, bool dodge);

};

// ----------------------------------------------------------------------------
// buff
// ----------------------------------------------------------------------------
struct combat_buff_t {
    const tagProtoBuff* proto;                    // 原型
    combat_pet_t* adder;                        // 添加者
    combat_pet_t* owner;                        // 被添加者
    int num;                                    // 叠加次数
    int round;                                    // 回合数

    combat_buff_t() {
        proto = NULL;
        adder = NULL;
        owner = NULL;
        num = 0;
        round = 0;
    }
    ~combat_buff_t() {
        proto = NULL;
        adder = NULL;
        owner = NULL;
        num = 0;
        round = 0;
    }

    void on_add();
    void on_cancel();
    void on_remove();
    void on_round();
};

// ----------------------------------------------------------------------------
// 效果记录
// ----------------------------------------------------------------------------
struct log_record {
    int32_t buffid;
    int32_t skillid;
    int32_t sprite_skillid;

    bool self_cast;

    int32_t damage;
    int32_t heal;

    int32_t att;
    int32_t flat;
    int32_t pct;

    vector<int32_t> buff_added;
    vector<int32_t> buff_removed;

    log_record() {
        buffid = -1;
        skillid = -1;
        sprite_skillid = -1;

        damage = 0;
        heal = 0;

        self_cast = false;

        att = -1;
        flat = 0;
        pct = 0;

        buff_added.clear();
        buff_removed.clear();
    }
};

// ----------------------------------------------------------------------------
// 效果日志 用于生成战斗序列
// ----------------------------------------------------------------------------
struct mod_log {
    map<int32_t, log_record> effect;    // id effect 若id为正为自己释放，否则为对方释放
    vector<int32_t> buff_removed;        // 移除的buff
    int32_t calced_damage;                // 普通计算伤害
    int32_t total_damage;                // 普通计算伤害外所有技能造成的伤害和
    int32_t total_heal;                    // 所有技能造成的治疗和
    bool crit;                            // 暴击
    bool miss;                            // 未命中
    bool immunity;                        // 免疫
    int castnum;                        // 技能释放数量
    int32_t rewardid;					 // combatreward

    bool affected;

    void reset() {
    	rewardid = -1;
        affected = false;
        castnum = 0;
        immunity = false;
        miss = false;
        crit = false;
        total_heal = 0;
        total_damage = 0;
        calced_damage = 0;
        buff_removed.clear();
        effect.clear();
    }
};

// ----------------------------------------------------------------------------
// 宠物
// ----------------------------------------------------------------------------
struct combat_pet_t {

    // 用于填写战斗序列 ----------------------------------------------------------
    mod_log _log;

    const mod_log &clog() { return _log; }
    mod_log &log() { _log.affected = true; return _log; }

    log_record &log_skill(int32_t id, combat_pet_t* initer);
    log_record &log_buff(int32_t id, combat_pet_t* initer);
    log_record &log_spriteskill(int32_t id, int32_t side);

    bool is_affected() { return _log.affected; }
    void fill_ocombatpeteffect(cs::OCombatPetEffect* oeffect);

    // 数据 --------------------------------------------------------------------
    const tagProtoPet* proto;                            // 原型
    combat_unit_t* unit;                                // 所属阵营
    string name;                                        // 名字
    att_t att;                                            // 属性
    int pos;                                            // 位置
    int hp;                                                // 血量
    int level;                                            // 等级
    int combatforce;										// 战力
    EQuality quality;
    int act_num;                                        // 行动次数
    bool mianyi;                                        // 是否免疫
    bool dizzy;                                            // 是否眩晕
    bool dummy;                                            // 是否封技
    bool frozen;                                        // 是否冰冻
    bool multi_cast;                                    // 是否连续攻击（加行动次数时用）

    const tagProtoSkill* actskill = NULL;				// actnum skill
    combat_pet_t* actskilliniter = NULL;

    bool is_dead() { return hp <= 0; }                    // 是否已经死亡
    ptr_map<int32_t, combat_skill_t*> skill;                // 技能
    ptr_map<int32_t, combat_buff_t*> buff;                    // buff

    void heal(int32_t value) {                            // 治疗
        if (value <= 0)
            return;

        hp += value;
        hp = cut(hp, 0, att.get(EPA_Hp));
    }
    void damage(int32_t value) {                        // 伤害
        if (value <= 0)
            return;

        hp -= value;
        hp = cut(hp, 0, att.get(EPA_Hp));
    }

    combat_pet_t() {
        _log.reset();

        quality = EQ_White;
        proto = NULL;
        pos = -1;
        unit = NULL;
        hp = 0;
        level = 1;
        act_num = 0;
        mianyi = false;
        dizzy = false;
        dummy = false;
        frozen = false;
        multi_cast = false;
    }

    // 初始化销毁等等 -------------------------------------------------------------
    bool init(pet_t* pet, const vector<att_mod_t> &mods, bool player = false);
    void destroy();

    // 检查是否死亡，然后做一些处理
    void check_dead();

    // 关于buff
    void clear_allbuff(vector<int32_t>* ids, bool self);
    bool add_buff(int32_t buffid, combat_pet_t* adder);
    void update_buff();

    // 对于每个技能
    void for_each_skill(function<void(combat_skill_t*)> cb, bool reverse = false);

    // 更新状态 ------------------------------------------------------------------
    void _update_status();
};

struct simple_player_info_t;

// ----------------------------------------------------------------------------
// 战斗阵营
// ----------------------------------------------------------------------------
struct combat_unit_t {
    int side;                            // 那一方
    combat_pet_t* pet[3];                // 所有宠物
    combat_sprite_t* sprite;            // 所有精灵
    const simple_player_info_t* info;   // 名称
    int angry;                            // 怒气

    combat_unit_t() {
        side = -1;
        for (int i=0; i<3; ++i)
            pet[i] = NULL;
        sprite = NULL;

        angry = 0;
        info = NULL;
    }

    ~combat_unit_t() {
        side = -1;
        for (int i=0; i<3; ++i)
            pet[i] = NULL;
        sprite = NULL;

        angry = 0;
    }

    vector<att_mod_t > mods; // att, value
    void gather_mods(unit_t* unit);        // 生成影响

    // 初始化销毁
    bool init(unit_t* unit);
    void destroy();
};

extern void g_combatcookie(player_t* player1, player_t* player2, int combatreward);
extern bool g_combat(unit_t* ud1, unit_t* ud2, cs::OCombat* ocombat, int32_t* ud2hp = NULL);
extern bool g_combat(player_t* player, int32_t level, cs::OCombat* ocombat);
extern bool g_combat(player_t* player, pet_t* pet, int32_t level, cs::OCombat* ocombat);

#endif /* COMBAT_H_ */
